package com.yiyi.credit.manage.abutment.common.utils;

import com.yiyi.credit.manage.abutment.common.constant.HttpConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class WebUtil {

    private static final int DEFAULT_TIMEOUT = 120000;
    private static final CloseableHttpClient httpclient = HttpClients.createDefault();
    private static final CloseableHttpClient httpsclient;
    private static Logger logger = LoggerFactory.getLogger(WebUtil.class);

    static {
        try {
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            final SSLSocketFactory ssf = sslContext.getSocketFactory();

            httpsclient = HttpClientBuilder.create()
                    .setSSLContext(sslContext)
                    .setSSLHostnameVerifier((name, session) -> true)
                    .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, (name, session) -> true))
                    .build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    }


    public static String doHttpsGet(String url) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, KeyManagementException {
        logger.info("请求 : {}", url);
        String response = "";
        try {
            RequestConfig requestConfig =
                    RequestConfig.custom().setSocketTimeout(DEFAULT_TIMEOUT).setConnectTimeout(DEFAULT_TIMEOUT).build();
            HttpGet httpGet = new HttpGet(url);
            httpGet.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpGet.setConfig(requestConfig);

            response = httpsclient.execute(httpGet, utf8ResponseHandler());
            logger.info("请求返回结果： {}", response);
            httpGet.abort();
            httpGet.releaseConnection();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw e;
        }

        return response;
    }

    public static String doPost(String url, String params)
            throws IOException {

        return doPost(url, params, DEFAULT_TIMEOUT);
    }

    public static String doPost(String url, Map<String, String> params)
            throws IOException {

        return doPost(url, params, DEFAULT_TIMEOUT);
    }

    private static String doPost(String url, String params, int timeout)
            throws IOException {
        String response = "";
        logger.debug("请求数据：, url: {}, params: {}", url, params);
        try {
            RequestConfig requestConfig =
                    RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setConfig(requestConfig);

            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentEncoding("UTF-8");
            httpPost.setEntity(stringEntity);
            long start = System.currentTimeMillis();
            response = httpclient.execute(httpPost, responseHandler());
            long end = System.currentTimeMillis();
            if (end - start > 1000) {
                logger.warn("push job cost too mush time : {} .  url : {}",
                        (end - start), url);
            }
            logger.info("请求返回结果： {}", response);
            httpPost.abort();
            httpPost.releaseConnection();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw e;
        }
        return response;

    }

    private static String doPost(String url, Map<String, String> params, int timeout)
            throws IOException {

        if (logger.isDebugEnabled())
            logger.debug("请求数据, url: {}", buildUrl(url, params));
        try {
            RequestConfig requestConfig =
                    RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(buildFormParams(params));
            long start = System.currentTimeMillis();
            String response = httpclient.execute(httpPost, responseHandler());
            long end = System.currentTimeMillis();
            if (end - start > 1000) {
                logger.warn("push job cost too mush time : {} . , url : {}",
                        (end - start), url);
            }
            logger.info("请求返回结果： {}", response);
            httpPost.abort();
            httpPost.releaseConnection();
            return response;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw e;
        }
    }


    public static String doPostHttps(String url, String params)
            throws IOException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException {
        String response = "";
        logger.debug("请求数据：, url: {}, params: {}", url, params);

        try {
            RequestConfig requestConfig =
                    RequestConfig.custom().setSocketTimeout(DEFAULT_TIMEOUT).setConnectTimeout(DEFAULT_TIMEOUT).build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setConfig(requestConfig);

            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentEncoding("UTF-8");
            httpPost.setEntity(stringEntity);

            response = httpsclient.execute(httpPost, responseHandler());
            logger.info("请求返回结果： {}", response);
            httpPost.abort();

        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw e;
        }
        return response;

    }

    private static ResponseHandler<String> responseHandler() {

        return response -> {
            int status = response.getStatusLine().getStatusCode();
            if (status >= HttpConstant.SUCCESS && status < HttpConstant.ERROR) {
                HttpEntity entity = response.getEntity();
                return entity != null ? EntityUtils.toString(entity) : null;
            } else {
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
        };
    }


    private static ResponseHandler<String> utf8ResponseHandler() {

        return response -> {
            int status = response.getStatusLine().getStatusCode();
            if (status >= HttpConstant.SUCCESS && status < HttpConstant.ERROR) {
                HttpEntity entity = response.getEntity();
                return entity != null ? EntityUtils.toString(entity, "utf-8") : null;
            } else {
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
        };
    }

    private static UrlEncodedFormEntity buildFormParams(Map<String, String> params) {

        List<NameValuePair> formParams = new ArrayList<>();
        if (params != null) {
            params.entrySet().forEach(entry -> formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue())));
        }
        return new UrlEncodedFormEntity(formParams, Consts.UTF_8);
    }

    public static String buildUrl(String url, Map<String, String> params) {
        if (StringUtils.isEmpty(url)) {
            return null;
        }

        StringBuilder urlBuilder = new StringBuilder(url).append("?");
        if (params != null) {
            params.entrySet().forEach(entry -> {
                try {
                    urlBuilder.append(entry.getKey())
                            .append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8")).append("&");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            });
        }
        urlBuilder.setLength(urlBuilder.length() - 1);
        return urlBuilder.toString();
    }
}
